tests = [
######################### badlex
{ # unknown symbol
	"token" : [ [ "' '", ], ],
	"input" : r"@",
	"yyerror" : [ 1, ],
},
{ # single '
	"token" : [ [ "' '", ], ],
	"input" : r"'",
	"yyerror" : [ 1, ],
},
{ # single "
	"token" : [ [ "' '", ], ],
	"input" : r"\"",
	"yyerror" : [ 1, ],
},
{ # multi errors
	"token" : [ [ "' '", ], [ "' '", ], ],
	"input" : r"\"'",
	"yyerror" : [ 1, 1, ],
},
######################### keyword
{
	"token" : [ [ "L_BREAK", "0", ], ],
	"input" : "break",
},
{
	"token" : [ [ "L_CONTINUE", "0", ], ],
	"input" : "continue",
},
{
	"token" : [ [ "L_DO", "0", ], ],
	"input" : "do",
},
{
	"token" : [ [ "L_ELSE", "0", ], ],
	"input" : "else",
},
{
	"token" : [ [ "L_BASIC_TYPE", "TYPE_REAL", ], ],
	"input" : "float",
},
{
	"token" : [ [ "L_FOR", "0", ], ],
	"input" : "for",
},
{
	"token" : [ [ "L_FOREACH", "0", ], ],
	"input" : "foreach",
},
{
	"token" : [ [ "L_IF", "0", ], ],
	"input" : "if",
},
{
	"token" : [ [ "L_IN", "0", ], ],
	"input" : "in",
},
{
	"token" : [ [ "L_BASIC_TYPE", "TYPE_NUMBER", ], ],
	"input" : "int",
},
{
	"token" : [ [ "L_BASIC_TYPE", "TYPE_MAPPING", ], ],
	"input" : "mapping",
},
{
	"token" : [ [ "L_BASIC_TYPE", "TYPE_ANY", ], ],
	"input" : "mixed",
},
{
	"token" : [ [ "L_BASIC_TYPE", "TYPE_OBJECT", ], ],
	"input" : "object",
},
{
	"token" : [ [ "L_RETURN", "0", ], ],
	"input" : "return",
},
{
	"token" : [ [ "L_BASIC_TYPE", "TYPE_STRING", ], ],
	"input" : "string",
},
{
	"token" : [ [ "L_BASIC_TYPE", "TYPE_VOID", ], ],
	"input" : "void",
},
{
	"token" : [ [ "L_WHILE", "0", ], ],
	"input" : "while",
},
######################### efun
{
	"token" : [ [ "L_DEFINED_NAME", "call_other", "IHE_EFUN", "1", ], ],
	"input" : "call_other",
},
{
	"token" : [ [ "L_DEFINED_NAME", "evaluate", "IHE_EFUN", "1", ], ],
	"input" : "evaluate",
},
{
	"token" : [ [ "L_DEFINED_NAME", "new", "IHE_EFUN", "1", ], ],
	"input" : "new",
},
{
	"token" : [ [ "L_DEFINED_NAME", "this_object", "IHE_EFUN", "1", ], ],
	"input" : "this_object",
},
{
	"token" : [ [ "L_DEFINED_NAME", "to_float", "IHE_EFUN", "1", ], ],
	"input" : "to_float",
},
{
	"token" : [ [ "L_DEFINED_NAME", "to_int", "IHE_EFUN", "1", ], ],
	"input" : "to_int",
},
######################### identifier
{
	"token" : [ [ "L_IDENTIFIER", "ident", ], ],
	"input" : r"ident",
},
{
	"token" : [ [ "L_IDENTIFIER", "_ident", ], ],
	"input" : r"_ident",
},
{
	"token" : [ [ "L_IDENTIFIER", "ident_08", ], ],
	"input" : r"ident_08",
},
######################### string
{
	"token" : [ [ "L_STRING", "a_0", ], ],
	"input" : r"\"a_0\"",
},
{
	"token" : [ [ "L_STRING", r"l\tp\tc", ], ],
	"input" : r"\"l\\tp	c\"",
},
{ # empty string
	"token" : [ [ "L_STRING", "", ], ],
	"input" : r"\"\"",
},
######################### string - backslash
{
	"token" : [ [ "L_STRING", r"\n", ], ],
	"input" : r"\"\\n\"",
},
{
	"token" : [ [ "L_STRING", r"\t", ], ],
	"input" : r"\"\\t\"",
},
{
	"token" : [ [ "L_STRING", r"\r", ], ],
	"input" : r"\"\\r\"",
},
{
	"token" : [ [ "L_STRING", r"\b", ], ],
	"input" : r"\"\\b\"",
},
{
	"token" : [ [ "L_STRING", r'\"', ], ],
	"input" : r"\"\\\"\"",
},
{
	"token" : [ [ "L_STRING", r"\\", ], ],
	"input" : r"\"\\\\\"",
},
{ # bad \
	"token" : [ [ "L_STRING", r"?", ], ],
	"input" : r"\"\\?\"",
	"yywarn": [ 1, ],
},
######################### char
{
	"token" : [ [ "L_NUMBER", "'a'", ], ],
	"input" : "'a'",
},
{
	"token" : [ [ "L_NUMBER", "'Z'", ], ],
	"input" : "'Z'",
},
{
	"token" : [ [ "L_NUMBER", "'0'", ], ],
	"input" : "'0'",
},
{
	"token" : [ [ "L_NUMBER", "'9'", ], ],
	"input" : "'9'",
},
{
	"token" : [ [ "L_NUMBER", "'?'", ], ],
	"input" : "'?'",
},
{
	"token" : [ [ "L_NUMBER", "'\"'", ], ],
	"input" : r"'\"'",
},
{ # bad ending
	"token" : [ [ "L_NUMBER", "0", ], ],
	"input" : "'ab'",
	"yyerror" : [ 1, ],
},
{ # bad empty char
	"token" : [ [ "' '", ], [ "' '", ], ],
	"input" : "''",
	"yyerror" : [ 1, 1, ],
},
######################## char - backslash
{
	"token" : [ [ "L_NUMBER", r"'\n'", ], ],
	"input" : r"'\\n'",
},
{
	"token" : [ [ "L_NUMBER", r"'\t'", ], ],
	"input" : r"'\\t'",
},
{
	"token" : [ [ "L_NUMBER", r"'\r'", ], ],
	"input" : r"'\\r'",
},
{
	"token" : [ [ "L_NUMBER", r"'\b'", ], ],
	"input" : r"'\\b'",
},
{ # \'
	"token" : [ [ "L_NUMBER", r"'\''", ], ],
	"input" : r"'\\''",
},
{ # \"
	"token" : [ [ "L_NUMBER", r"'\"'", ], ],
	"input" : r"'\\\"'",
},
{ # \\
	"token" : [ [ "L_NUMBER", r"'\\'", ], ],
	"input" : r"'\\\\'",
},
{ # \oct - minimum
	"token" : [ [ "L_NUMBER", r"0", ], ],
	"input" : r"'\\0'",
},
{ # \oct
	"token" : [ [ "L_NUMBER", r"10", ], ],
	"input" : r"'\\12'",
},
{ # \oct - maximum
	"token" : [ [ "L_NUMBER", r"63", ], ],
	"input" : r"'\\77'",
},
{ # \oct - overflow
	"token" : [ [ "L_NUMBER", r"'x'", ], ],
	"input" : r"'\\123'",
	"yywarn" : [ 1, ],
},
{ # \oct - invalid
	"token" : [ [ "L_NUMBER", r"'8'", ], ],
	"input" : r"'\\8'",
	"yywarn" : [ 1, ],
},
######################## real - with dot
{
	"token" : [ [ "L_REAL", r"0", ], ],
	"input" : r"0.",
},
{
	"token" : [ [ "L_REAL", r"0.9", ], ],
	"input" : r".9",
},
{
	"token" : [ [ "L_REAL", r"1.2", ], ],
	"input" : r"1.2",
},
{
	"token" : [ [ "L_REAL", r"30000", ], ],
	"input" : r"3.e4",
},
{
	"token" : [ [ "L_REAL", r"5000000", ], ],
	"input" : r"5.E6",
},
{
	"token" : [ [ "L_REAL", r"0.0000008", ], ],
	"input" : r"8.e-7",
},
{
	"token" : [ [ "L_REAL", r"9.1", ], ],
	"input" : r"9.1e+0",
},
{
	"token" : [ [ "L_REAL", r"987.65432", ], ],
	"input" : r"9876.5432e-1",
},
{ # not real
	"token" : [ [ "' '", ], [ "L_IDENTIFIER", "e", ], ],
	"input" : r".e",
	"yyerror" : [ 1, 0, ],
},
######################## real - without dot
{
	"token" : [ [ "L_REAL", r"0", ], ],
	"input" : r"0E+0",
},
{
	"token" : [ [ "L_REAL", r"1", ], ],
	"input" : r"01E-00",
},
{
	"token" : [ [ "L_REAL", r"90", ], ],
	"input" : r"9E+1",
},
{
	"token" : [ [ "L_REAL", r"0.002", ], ],
	"input" : r"2E-3",
},
{
	"token" : [ [ "L_REAL", r"400000", ], ],
	"input" : r"4e5",
},
{
	"token" : [ [ "L_REAL", r"0.00000067", ], ],
	"input" : r"67e-8",
},
{ # not a real
	"token" : [ [ "L_NUMBER", r"3", ], [ "L_IDENTIFIER", "e", ], ],
	"input" : r"3e",
},
{ # not a real
	"token" : [ [ "L_IDENTIFIER", "e3", ], ],
	"input" : r"e3",
},
######################## number - dec
{
	"token" : [ [ "L_NUMBER", r"0", ], ],
	"input" : r"0",
},
{
	"token" : [ [ "L_NUMBER", r"1", ], ],
	"input" : r"1",
},
{
	"token" : [ [ "L_NUMBER", r"9", ], ],
	"input" : r"09",
},
{
	"token" : [ [ "L_NUMBER", r"12345678", ], ],
	"input" : r"12345678",
},
######################## L_ARRAY_OPEN 
{
	"token" : [ [ "L_ARRAY_OPEN", ], ],
	"input" : "({",
},
{ # whitespace within
	"token" : [ [ "L_ARRAY_OPEN", ], ],
	"input" : "(  {",
},
{ # whitespace within
	"token" : [ [ "L_ARRAY_OPEN", ], ],
	"input" : "(\t{",
},
{ # newline within
	"token" : [ [ "L_ARRAY_OPEN", ], ],
	"input" : "(\\n\\n{",
	"lineno": [3, ],
},
######################## L_MAPPING_OPEN 
{
	"token" : [ [ "L_MAPPING_OPEN", ], ],
	"input" : "([",
},
{ # whitespace within
	"token" : [ [ "L_MAPPING_OPEN", ], ],
	"input" : "(  [",
},
{ # whitespace within
	"token" : [ [ "L_MAPPING_OPEN", ], ],
	"input" : "(\t[",
},
{ # newline within
	"token" : [ [ "L_MAPPING_OPEN", ], ],
	"input" : "(\\n\\n[",
	"lineno": [3, ],
},
######################### whitespace
{
	"token" : [  ],
	"input" : r" ",
},
{
	"token" : [  ],
	"input" : r"\t",
},
{
	"token" : [  ],
	"input" : r"\v",
},
{
	"token" : [  ],
	"input" : r"\f",
},
{
	"token" : [  ],
	"input" : r"\r",
},
######################### newline
{
	"token" : [  ],
	"input" : r"\n",
	"lineno" : [ 2, ],
},
######################## others
{
	"token" : [ [ "'+'", ], ],
	"input" : "+",
},
{
	"token" : [ [ "L_ARROW", ], ],
	"input" : "->",
},
{
	"token" : [ [ "'-'", ], ],
	"input" : "-",
},
{
	"token" : [ [ "L_LAND", ], ],
	"input" : "&&",
},
{
	"token" : [ [ "L_LOR", ], ],
	"input" : "||",
},
{
	"token" : [ [ "L_ORDER", "F_LE", ], ],
	"input" : "<=",
},
{
	"token" : [ [ "L_ORDER", "F_LT", ], ],
	"input" : "<",
},
{
	"token" : [ [ "L_ORDER", "F_GE", ], ],
	"input" : ">=",
},
{
	"token" : [ [ "L_ORDER", "F_GT", ], ],
	"input" : ">",
},
{
	"token" : [ [ "'*'", ], ],
	"input" : "*",
},
{
	"token" : [ [ "'%'", ], ],
	"input" : "%",
},
{
	"token" : [ [ "'/'", ], ],
	"input" : "/",
},
{
	"token" : [ [ "L_EQ", ], ],
	"input" : "==",
},
{
	"token" : [ [ "L_ASSIGN", "F_ASSIGN", ], ],
	"input" : "=",
},
{
	"token" : [ [ "'('", ], ],
	"input" : "(",
},
{
	"token" : [ [ "')'", ], ],
	"input" : ")",
},
{
	"token" : [ [ "'{'", ], ],
	"input" : "{",
},
{
	"token" : [ [ "'}'", ], ],
	"input" : "}",
},
{
	"token" : [ [ "'['", ], ],
	"input" : "[",
},
{
	"token" : [ [ "']'", ], ],
	"input" : "]",
},
{
	"token" : [ [ "';'", ], ],
	"input" : ";",
},
{
	"token" : [ [ "','", ], ],
	"input" : ",",
},
{
	"token" : [ [ "L_NE", ], ],
	"input" : "!=",
},
{
	"token" : [ [ "L_NOT", ], ],
	"input" : "!",
},
{
	"token" : [ [ "':'", ], ],
	"input" : ":",
},
######################### comment
{
	"token" : [  ],
	"input" : r"// ba la la",
},
{
	"token" : [ [ "';'", ], ],
	"input" : r";// ba la la",
},
{
	"token" : [  ],
	"input" : r"/* hello */",
},
{
	"token" : [ [ "L_IDENTIFIER", "a", ], [ "L_IDENTIFIER", "b", ], ],
	"input" : r"a/* hello */b",
},
{
	"token" : [ [ "L_IDENTIFIER", "a", ], ],
	"input" : r"/* hello \n world */ a",
	"lineno" : [ 2, ],
},
{ # unterminated comment
	"token" : [  ],
	"input" : r"/*",
	"extra_yyerror" : 1,
},
	]

def gen_test():
	outFile = open("lexer_tests.c", "w")

	it = 1
	for test in tests:
		outFile.write("static void test_%d()\n{\n" % it)

		# tokens
		if len(test["token"]) == 0:
			# no token
			if test.has_key("extra_yywarn"):
				outFile.write("\textra_yywarns = %d;\n" % test["extra_yywarn"])
			else:
				outFile.write("\textra_yywarns = 0;\n");

			if test.has_key("extra_yyerror"):
				outFile.write("\textra_yyerrors = %d;\n" % test["extra_yyerror"])
			else:
				outFile.write("\textra_yyerrors = 0;\n");

		io = 0
		for token in test["token"]:
			out = "\toutput[%d]." % io

			if len(token) == 1: # no yylval
				outFile.write(out + "type = -1;\n");
				outFile.write(out + "u.number = %s;\n" % token[0])
			else:
				# type
				outFile.write(out + "type = %s;\n" % token[0])

				# value
				if token[0] == "L_REAL":
					outFile.write(out + "u.real = %s;\n" % token[1])

				elif token[0] == "L_DEFINED_NAME":
					outFile.write("\tident_hash_elem_t ident_%d;\n" % io)
					outFile.write("\tident_%d.name = \"%s\";\n" % (io, token[1]))
					outFile.write("\tident_%d.token = %s;\n" % (io, token[2]))
					outFile.write("\tident_%d.sem_value = %s;\n" % (io, token[3]))
					outFile.write(out + "u.ihe = &ident_%d;\n" % io)

				elif token[0] == "L_STRING" or token[0] == "L_IDENTIFIER":
					outFile.write(out + 'u.string = "%s";\n' % token[1])

				else:
					outFile.write(out + "u.number = %s;\n" % token[1])

			# lineno	
			lineno = -1
			if test.has_key("lineno"):
				lineno = test["lineno"][io]
			outFile.write(out + "lineno = %d;\n" % lineno)

			# yywarn
			yywarn = 0
			if test.has_key("yywarn"):
				yywarn = test["yywarn"][io]
			outFile.write(out + "yywarn = %d;\n" % yywarn)

			# yyerror
			yyerror = 0
			if test.has_key("yyerror"):
				yyerror = test["yyerror"][io]
			outFile.write(out + "yyerror = %d;\n" % yyerror)

			io += 1
			
		# run_test
		outFile.write('\trun_test("%s", %s);\n}\n\n' % (test["input"], io))

		it += 1
	
	outFile.write("static void run_testsuite()\n{\n")
	
	for i in range(1, it):
		outFile.write("\ttest_%d();\n" % i)

	outFile.write("}\n\n")	

if __name__=="__main__":
	gen_test()
